package cn.zwx.zookeeper.config.example.connect;

import cn.zwx.zookeeper.config.example.config.ymal.RetryPolicyConfig;
import cn.zwx.zookeeper.config.example.config.ymal.ZookeeperConfig;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Constructor;
import java.util.Objects;

/**
 * @author zhangwenxue
 */
public class ZookeeperConnectHandler{

    private ZookeeperConfig zookeeperConfig;

    final  RetryPolicy DEFAULT_RETRY_POLICY = new ExponentialBackoffRetry(1000, 3);


    public ZookeeperConnectHandler( ZookeeperConfig zookeeperConfig) {
        this.zookeeperConfig = zookeeperConfig;
    }

    /**
     * 获取zookeeper 链接对象
     */
   public CuratorFramework getCuratorFramework(){
      if (Objects.isNull(zookeeperConfig)) {
           return null;
      }
       String connectString = zookeeperConfig.getConnectString();
       Integer connectionTimeoutMs = zookeeperConfig.getConnectionTimeoutMs();
       Integer sessionTimeoutMs = zookeeperConfig.getSessionTimeoutMs();
       String namespace = zookeeperConfig.getNamespace();
       RetryPolicyConfig retryPolicy = zookeeperConfig.getRetryPolicy();
       if (Objects.isNull(retryPolicy)){
           return this.getDefaultCuratorFramework(connectString, connectionTimeoutMs, sessionTimeoutMs, namespace);
       }else {
           return getCuratorFramework(connectString, connectionTimeoutMs, sessionTimeoutMs, namespace, retryPolicy);
       }

   }


    private CuratorFramework getCuratorFramework(String connectString, Integer connectionTimeoutMs, Integer sessionTimeoutMs, String namespace, RetryPolicyConfig retryPolicy) {
        RetryPolicy customRetryPolicy = null;
        try {
            Class<?> aClass = Class.forName(retryPolicy.getType());
            Constructor<?> constructor = ReflectionUtils.accessibleConstructor(aClass, int.class, int.class, int.class);
            Object newInstance = constructor.newInstance(retryPolicy.getBaseSleepTimeMs(), retryPolicy.getMaxRetries(), retryPolicy.getMaxSleepMs());
            customRetryPolicy = (ExponentialBackoffRetry) newInstance;
        }catch (Exception e){
          e.printStackTrace();
        }
        if (Objects.isNull(customRetryPolicy)){
            return this.getDefaultCuratorFramework(connectString, connectionTimeoutMs, sessionTimeoutMs, namespace);
        }

        return this.getCuratorFramework(connectString, connectionTimeoutMs, sessionTimeoutMs, namespace,customRetryPolicy);
    }

    private CuratorFramework getDefaultCuratorFramework(String connectString, Integer connectionTimeoutMs, Integer sessionTimeoutMs, String namespace) {
        return CuratorFrameworkFactory.builder()
                .connectString(connectString)
                .sessionTimeoutMs(sessionTimeoutMs)
                .connectionTimeoutMs(connectionTimeoutMs)
                .retryPolicy(DEFAULT_RETRY_POLICY)
                .namespace(namespace)
                .build();
    }

    private CuratorFramework getCuratorFramework(String connectString, Integer connectionTimeoutMs, Integer sessionTimeoutMs, String namespace,RetryPolicy retryPolicy) {
        return CuratorFrameworkFactory.builder()
                .connectString(connectString)
                .sessionTimeoutMs(sessionTimeoutMs)
                .connectionTimeoutMs(connectionTimeoutMs)
                .retryPolicy(retryPolicy)
                .namespace(namespace)
                .build();
    }


}
